import os
import re
import logging
import fitz  # PyMuPDF for PDF processing
import docx  # python-docx for DOCX processing
from .models import ParsedQuestion, ParserTask
from django.utils import timezone

logger = logging.getLogger(__name__)

def detect_answer(content):
    """从题目内容中检测答案"""
    if not content:
        return None
    
    logger.debug(f"开始检测答案: {content[:100]}...")
        
    # 匹配题目中的答案标记，如 (A)、（B）等
    answer_pattern = r'[（\(]\s*([A-D])\s*[）\)]'
    match = re.search(answer_pattern, content, re.IGNORECASE)
    
    if match:
        answer = match.group(1).upper()
        logger.debug(f"匹配到答案标记(A): {answer}")
        return answer
    
    # 匹配题目中的多选答案标记，如 (.AB)、（.ABC）等
    multi_answer_pattern = r'[（\(]\s*\.\s*([A-D]+)\s*[）\)]'
    multi_match = re.search(multi_answer_pattern, content, re.IGNORECASE)
    
    if multi_match:
        answer = multi_match.group(1).upper()
        logger.debug(f"匹配到多选答案标记(.AB): {answer}")
        return answer
    
    # 匹配题目中的多选答案标记，如 (AB)、（ABC）等
    direct_multi_answer_pattern = r'[（\(]\s*([A-D]{2,})\s*[）\)]'
    direct_multi_match = re.search(direct_multi_answer_pattern, content, re.IGNORECASE)
    
    if direct_multi_match:
        answer = direct_multi_match.group(1).upper()
        logger.debug(f"匹配到直接多选答案标记(AB): {answer}")
        return answer
    
    # 匹配题目末尾的答案标记，如 A、B、C、D
    end_answer_pattern = r'答案[是为：:]\s*([A-D]+)'
    end_match = re.search(end_answer_pattern, content, re.IGNORECASE)
    
    if end_match:
        answer = end_match.group(1).upper()
        logger.debug(f"匹配到末尾答案标记(答案是A): {answer}")
        return answer
    
    # 匹配题目中的答案标记，如 答案：A 或 答：B
    simple_answer_pattern = r'答案?[：:]\s*([A-D]+)'
    simple_match = re.search(simple_answer_pattern, content, re.IGNORECASE)
    
    if simple_match:
        answer = simple_match.group(1).upper()
        logger.debug(f"匹配到简单答案标记(答案:A): {answer}")
        return answer
    
    # 匹配题目中的答案标记，如 正确答案：A 或 正确答案:B
    correct_answer_pattern = r'正确答案[：:]\s*([A-D]+)'
    correct_match = re.search(correct_answer_pattern, content, re.IGNORECASE)
    
    if correct_match:
        answer = correct_match.group(1).upper()
        logger.debug(f"匹配到正确答案标记(正确答案:A): {answer}")
        return answer
    
    # 匹配题目中的答案标记，如 "答：选A" 或 "答案：选择B"
    select_answer_pattern = r'答案?[：:]\s*选择?\s*([A-D]+)'
    select_match = re.search(select_answer_pattern, content, re.IGNORECASE)
    
    if select_match:
        answer = select_match.group(1).upper()
        logger.debug(f"匹配到选择答案标记(答案:选A): {answer}")
        return answer
    
    # 匹配题目中的答案标记，如 "本题答案[是]A" 或 "此题答案[是]B"
    this_answer_pattern = r'[本此]题答案[是为]?\s*([A-D]+)'
    this_match = re.search(this_answer_pattern, content, re.IGNORECASE)
    
    if this_match:
        answer = this_match.group(1).upper()
        logger.debug(f"匹配到本题答案标记(本题答案是A): {answer}")
        return answer
    
    # 匹配题目中的答案标记，如 "参考答案：A" 或 "参考答案:B"
    reference_answer_pattern = r'参考答案[：:]\s*([A-D]+)'
    reference_match = re.search(reference_answer_pattern, content, re.IGNORECASE)
    
    if reference_match:
        answer = reference_match.group(1).upper()
        logger.debug(f"匹配到参考答案标记(参考答案:A): {answer}")
        return answer
    
    # 新增：匹配题目中的答案标记，如 "答对了：A" 或 "答对了:B"
    correct_pattern = r'答对了[：:]\s*([A-D]+)'
    correct_match = re.search(correct_pattern, content, re.IGNORECASE)
    
    if correct_match:
        answer = correct_match.group(1).upper()
        logger.debug(f"匹配到答对了标记(答对了:A): {answer}")
        return answer
    
    # 新增：匹配题目中的答案标记，如 "选A" 或 "选B"
    choose_pattern = r'选\s*([A-D]+)'
    choose_match = re.search(choose_pattern, content, re.IGNORECASE)
    
    if choose_match:
        answer = choose_match.group(1).upper()
        logger.debug(f"匹配到选择标记(选A): {answer}")
        return answer
    
    # 新增：匹配题目中的答案标记，如 "应选A" 或 "应该选B"
    should_choose_pattern = r'应(?:该)?选\s*([A-D]+)'
    should_choose_match = re.search(should_choose_pattern, content, re.IGNORECASE)
    
    if should_choose_match:
        answer = should_choose_match.group(1).upper()
        logger.debug(f"匹配到应选标记(应选A): {answer}")
        return answer
    
    # 新增：匹配题目中的答案标记，如 "选项A正确" 或 "选项B是对的"
    correct_option_pattern = r'选项\s*([A-D]+)\s*(?:正确|是对的|对)'
    correct_option_match = re.search(correct_option_pattern, content, re.IGNORECASE)
    
    if correct_option_match:
        answer = correct_option_match.group(1).upper()
        logger.debug(f"匹配到正确选项标记(选项A正确): {answer}")
        return answer
    
    logger.debug("未检测到答案")
    return None

def extract_options_from_text(text):
    """从文本中提取选项"""
    options = {}
    
    # 匹配选项格式：A. 选项内容 或 A、选项内容 或 A：选项内容 或 A. 选项内容
    option_patterns = [
        r'([A-E])[、.．:：]\s*([^A-E\n]+?)(?=\s*[A-E][、.．:：]|\s*$)',  # 常规格式
        r'([A-E])\.\s+([^A-E\n]+?)(?=\s*[A-E]\.\s+|\s*$)',  # A. 格式
        r'([A-E])\s*[.．、:：]\s*([^A-E\n]+?)(?=\s*[A-E]\s*[.．、:：]|\s*$)',  # 宽松格式
        r'选项\s*([A-E])[：:]\s*([^A-E\n]+?)(?=\s*选项\s*[A-E]\s*[：:]|\s*$)',  # 选项A：内容 格式
        r'([A-E])\s*[）\)]\s*([^A-E\n]+?)(?=\s*[A-E]\s*[）\)]|\s*$)',  # A) 格式
        r'[（\(]\s*([A-E])\s*[）\)]\s*([^A-E\n]+?)(?=\s*[（\(]\s*[A-E]\s*[）\)]|\s*$)',  # (A) 格式
        # 紧凑格式，如"A、德国 B、奥地利"
        r'([A-E])[、.．:：]\s*([^\n]+?)(?=\s+[A-E][、.．:：]|\s*$)',
    ]
    
    # 尝试不同的选项匹配模式
    for pattern in option_patterns:
        option_matches = list(re.finditer(pattern, text, re.DOTALL))
        if option_matches:
            for match in option_matches:
                option_letter = match.group(1).upper()
                option_content = match.group(2).strip()
                # 只有当选项内容不为空时才添加
                if option_content:
                    options[option_letter] = option_content
            
            # 如果找到了至少两个选项，认为匹配成功
            if len(options) >= 2:
                break
    
    # 如果没有找到足够的选项，尝试更宽松的匹配
    if len(options) < 2:
        # 尝试查找所有可能的选项标记
        all_options = re.findall(r'([A-E])[、.．:：]\s*([^A-E\n]{3,}?)(?=\n|$)', text, re.DOTALL)
        for option_letter, option_content in all_options:
            option_letter = option_letter.upper()
            option_content = option_content.strip()
            if option_content:
                options[option_letter] = option_content
        
        # 如果仍然没有找到足够的选项，尝试匹配紧凑格式的选项，如"A、德国 B、奥地利 C、中国 D、俄国"
        if len(options) < 2:
            # 紧凑格式，选项之间用空格分隔
            compact_pattern = r'([A-E])[、.．:：]\s*([^\n]+?)(?=\s+[A-E][、.．:：]|\s*$)'
            compact_options = re.findall(compact_pattern, text)
            for option_letter, option_content in compact_options:
                option_letter = option_letter.upper()
                option_content = option_content.strip()
                if option_content:
                    options[option_letter] = option_content
            
            # 如果仍然没有找到足够的选项，尝试更宽松的紧凑格式匹配
            if len(options) < 2:
                # 超级宽松格式，匹配任何以A-E开头的内容
                super_compact_pattern = r'([A-E])[、.．:：]\s*([^\s]+(?:\s+[^\s]+)*?)(?=\s+[A-E][、.．:：]|\s*$)'
                super_compact_options = re.findall(super_compact_pattern, text)
                for option_letter, option_content in super_compact_options:
                    option_letter = option_letter.upper()
                    option_content = option_content.strip()
                    if option_content:
                        options[option_letter] = option_content
    
    # 检查选项的连续性和完整性
    if options and all(letter in options for letter in ['A', 'B']):
        # 如果至少有A和B选项，检查是否有C、D选项
        expected_options = ['A', 'B', 'C', 'D']
        for i, letter in enumerate(expected_options):
            # 如果发现缺失的选项，尝试使用更宽松的模式查找
            if letter not in options and i > 0 and expected_options[i-1] in options:
                # 查找上一个选项之后的文本
                prev_letter = expected_options[i-1]
                prev_content = options[prev_letter]
                remaining_text = text[text.find(prev_content) + len(prev_content):]
                
                # 尝试在剩余文本中查找当前缺失的选项
                next_option_match = re.search(r'([' + letter + '])\s*[.．、:：]\s*([^\n]+?)(?=\n|$)', remaining_text)
                if next_option_match:
                    options[letter] = next_option_match.group(2).strip()
    
    return options

def parse_multiple_questions(text):
    """解析包含多个题目的文本块，将其分割为单独的题目"""
    if not text:
        return []
    
    logger.info(f"开始解析多个题目，文本长度: {len(text)}")
    
    # 首先处理题型标题，如"一、单项选择题"
    question_type_title_pattern = r'(?:^|\n)\s*([一二三四五六七八九十]+)[、.．]\s*(单项选择题|多项选择题|判断题|填空题|简答题|计算题|分析题)'
    question_type_match = re.search(question_type_title_pattern, text)
    current_question_type = "选择题"  # 默认题型
    
    if question_type_match:
        current_question_type = question_type_match.group(2)
        logger.info(f"检测到题型标题: {question_type_match.group(0)}, 题型: {current_question_type}")
        
        # 移除题型标题，避免将其误识别为题目
        text = text.replace(question_type_match.group(0), "", 1)
    
    # 使用正则表达式匹配题号开头的行来分割题目
    # 匹配如：5．题目内容、5. 题目内容、5、题目内容等格式
    question_start_patterns = [
        r'(?:^|\n)\s*(\d+)[\.．、]\s*',  # 数字+点/顿号格式，如"1、"
        r'(?:^|\n)\s*(\d+)\s*[\.．、]\s*',  # 数字+可能有空格+点/顿号格式
        r'(?:^|\n)\s*第\s*([一二三四五六七八九十\d]+)\s*题\s*',  # 第X题格式
        r'(?:^|\n)\s*[（\(]\s*(\d+)\s*[）\)]\s*',  # 带括号的数字：(1) 题目内容
        r'(?:^|\n)\s*题\s*(\d+)[\.．、]?\s*',  # 题号+数字格式：题1. 题目内容
        r'(?:^|\n)\s*问题\s*(\d+)[：:]\s*',  # 问题+数字格式：问题1：题目内容
        r'(?:^|\n)\s*([一二三四五六七八九十]+)[、.．]\s*',  # 中文数字+顿号格式：一、题目内容
    ]
    
    questions = []
    
    # 尝试不同的题目分割模式
    for pattern in question_start_patterns:
        # 查找所有题目的起始位置
        matches = list(re.finditer(pattern, text, re.DOTALL))
        
        # 如果找到了题目起始位置
        if matches:
            logger.info(f"使用模式 '{pattern}' 找到 {len(matches)} 个题目")
            
            # 跳过可能是题型标题的匹配
            if pattern == r'(?:^|\n)\s*([一二三四五六七八九十]+)[、.．]\s*' and len(matches) == 1:
                first_match = matches[0]
                first_match_text = text[first_match.start():first_match.start()+20].strip()
                if re.search(r'[一二三四五六七八九十]+[、.．]\s*(单项选择题|多项选择题|判断题|填空题|简答题|计算题|分析题)', first_match_text):
                    logger.info(f"跳过题型标题: {first_match_text}")
                    continue
            
            # 处理每个题目
            for i in range(len(matches)):
                start_pos = matches[i].start()
                question_number = matches[i].group(1)  # 获取题号
                
                # 如果是最后一个题目，结束位置是文本末尾
                if i == len(matches) - 1:
                    end_pos = len(text)
                else:
                    end_pos = matches[i + 1].start()
                
                # 提取题目文本
                question_text = text[start_pos:end_pos].strip()
                
                # 跳过可能是题型标题的匹配
                if re.search(r'^[一二三四五六七八九十]+[、.．]\s*(单项选择题|多项选择题|判断题|填空题|简答题|计算题|分析题)', question_text):
                    logger.info(f"跳过题型标题: {question_text[:20]}...")
                    continue
                
                # 解析单个题目
                parsed = parse_multiple_choice_question(question_text)
                if parsed:
                    # 确保题号被正确设置
                    if not parsed.get('question_number') and question_number:
                        try:
                            parsed['question_number'] = int(question_number)
                        except ValueError:
                            # 如果是中文数字，转换为阿拉伯数字
                            chinese_to_arabic = {'一': 1, '二': 2, '三': 3, '四': 4, '五': 5, 
                                                '六': 6, '七': 7, '八': 8, '九': 9, '十': 10}
                            if question_number in chinese_to_arabic:
                                parsed['question_number'] = chinese_to_arabic[question_number]
                            else:
                                parsed['question_number'] = question_number
                    
                    # 设置题型
                    if parsed.get('question_type') == '未分类' or not parsed.get('question_type'):
                        parsed['question_type'] = current_question_type
                    
                    questions.append(parsed)
                    logger.debug(f"成功解析题目 {question_number}: {parsed['content'][:50]}...")
                else:
                    logger.warning(f"无法解析题目 {question_number}")
            
            # 如果找到了题目，就不再尝试其他模式
            if questions:
                break
    
    # 如果没有找到多个题目，尝试使用选项分割文本
    if not questions:
        logger.info("未找到题号格式的题目，尝试使用选项A作为分隔符")
        
        # 尝试使用选项A作为分隔符
        option_a_patterns = [
            r'(?:^|\n)\s*[A][、.．:：]\s*',  # A. 或 A、 或 A: 格式
            r'(?:^|\n)\s*选项\s*[A][：:]\s*',  # 选项A: 格式
            r'(?:^|\n)\s*[A]\s*[）\)]\s*',  # A) 格式
            r'(?:^|\n)\s*[（\(]\s*[A]\s*[）\)]\s*'  # (A) 格式
        ]
        
        for pattern in option_a_patterns:
            # 查找所有A选项的位置
            option_a_matches = list(re.finditer(pattern, text))
            
            if len(option_a_matches) > 1:
                logger.info(f"使用选项A模式 '{pattern}' 找到 {len(option_a_matches)} 个可能的题目")
                
                # 如果找到多个A选项，可能是多个题目
                for i in range(len(option_a_matches) - 1):
                    current_pos = option_a_matches[i].start()
                    
                    # 向前查找题目内容
                    question_start = text.rfind('\n', 0, current_pos)
                    if question_start == -1:
                        question_start = 0
                    
                    # 向后查找到下一个A选项
                    next_pos = option_a_matches[i + 1].start()
                    
                    # 提取完整题目文本（包括题干和选项）
                    question_text = text[question_start:next_pos].strip()
                    
                    # 尝试从题目文本中提取题号
                    question_number = None
                    for num_pattern in question_start_patterns:
                        num_match = re.search(num_pattern, question_text)
                        if num_match:
                            question_number = num_match.group(1)
                            break
                    
                    # 解析单个题目
                    parsed = parse_multiple_choice_question(question_text)
                    if parsed:
                        # 确保题号被正确设置
                        if not parsed.get('question_number') and question_number:
                            try:
                                parsed['question_number'] = int(question_number)
                            except ValueError:
                                # 如果是中文数字，转换为阿拉伯数字
                                chinese_to_arabic = {'一': 1, '二': 2, '三': 3, '四': 4, '五': 5, 
                                                    '六': 6, '七': 7, '八': 8, '九': 9, '十': 10}
                                if question_number in chinese_to_arabic:
                                    parsed['question_number'] = chinese_to_arabic[question_number]
                                else:
                                    parsed['question_number'] = question_number
                        
                        # 设置题型
                        if parsed.get('question_type') == '未分类' or not parsed.get('question_type'):
                            parsed['question_type'] = current_question_type
                        
                        questions.append(parsed)
                        logger.debug(f"通过选项A分割成功解析题目: {parsed['content'][:50]}...")
                
                # 处理最后一个题目
                last_pos = option_a_matches[-1].start()
                question_start = text.rfind('\n', 0, last_pos)
                if question_start == -1:
                    question_start = 0
                
                question_text = text[question_start:].strip()
                
                # 尝试从题目文本中提取题号
                question_number = None
                for num_pattern in question_start_patterns:
                    num_match = re.search(num_pattern, question_text)
                    if num_match:
                        question_number = num_match.group(1)
                        break
                
                parsed = parse_multiple_choice_question(question_text)
                if parsed:
                    # 确保题号被正确设置
                    if not parsed.get('question_number') and question_number:
                        try:
                            parsed['question_number'] = int(question_number)
                        except ValueError:
                            # 如果是中文数字，转换为阿拉伯数字
                            chinese_to_arabic = {'一': 1, '二': 2, '三': 3, '四': 4, '五': 5, 
                                                '六': 6, '七': 7, '八': 8, '九': 9, '十': 10}
                            if question_number in chinese_to_arabic:
                                parsed['question_number'] = chinese_to_arabic[question_number]
                            else:
                                parsed['question_number'] = question_number
                    
                    # 设置题型
                    if parsed.get('question_type') == '未分类' or not parsed.get('question_type'):
                        parsed['question_type'] = current_question_type
                    
                    questions.append(parsed)
                    logger.debug(f"通过选项A分割成功解析最后一个题目: {parsed['content'][:50]}...")
                
                # 如果找到了题目，就不再尝试其他模式
                if questions:
                    break
    
    # 如果仍然没有找到多个题目，尝试作为单个题目解析
    if not questions:
        logger.info("未能分割出多个题目，尝试作为单个题目解析")
        parsed = parse_multiple_choice_question(text)
        if parsed:
            # 设置题型
            if parsed.get('question_type') == '未分类' or not parsed.get('question_type'):
                parsed['question_type'] = current_question_type
                
            questions.append(parsed)
            logger.debug(f"作为单个题目解析成功: {parsed['content'][:50]}...")
    
    # 按题号排序
    if questions:
        # 尝试将题号转换为整数进行排序
        def get_question_number(q):
            num = q.get('question_number')
            if num:
                try:
                    return int(num)
                except (ValueError, TypeError):
                    # 如果是中文数字，转换为阿拉伯数字
                    chinese_to_arabic = {'一': 1, '二': 2, '三': 3, '四': 4, '五': 5, 
                                        '六': 6, '七': 7, '八': 8, '九': 9, '十': 10}
                    if isinstance(num, str) and num in chinese_to_arabic:
                        return chinese_to_arabic[num]
            return float('inf')  # 没有题号的放在最后
        
        questions.sort(key=get_question_number)
    
    logger.info(f"共解析出 {len(questions)} 个题目")
    return questions

def parse_multiple_choice_question(text):
    """解析选择题，处理包含选项的题目"""
    if not text:
        return None
    
    logger.debug(f"开始解析题目: {text[:100]}...")
    
    # 尝试匹配题目编号和内容
    question_patterns = [
        # 数字+点/顿号格式：5．题目内容、5. 题目内容、5、题目内容
        r'^(\d+)[\.．、]\s*(.+?)(?=\s*[A-E][、.．:：]|\s*$)',
        # 带空格的数字+点/顿号格式
        r'^(\d+)\s*[\.．、]\s*(.+?)(?=\s*[A-E][、.．:：]|\s*$)',
        # 中文数字+顿号格式：一、题目内容
        r'^([一二三四五六七八九十]+)[、.．]\s*(.+?)(?=\s*[A-E][、.．:：]|\s*$)',
        # 带括号的数字：(1) 题目内容
        r'^[（\(]\s*(\d+)\s*[）\)]\s*(.+?)(?=\s*[A-E][、.．:：]|\s*$)',
        # 第X题格式：第一题 题目内容
        r'^第([一二三四五六七八九十\d]+)题\s*(.+?)(?=\s*[A-E][、.．:：]|\s*$)',
        # 题号+数字格式：题1. 题目内容
        r'^题\s*(\d+)[\.．、]?\s*(.+?)(?=\s*[A-E][、.．:：]|\s*$)',
        # 问题+数字格式：问题1：题目内容
        r'^问题\s*(\d+)[：:]\s*(.+?)(?=\s*[A-E][、.．:：]|\s*$)',
        # 更宽松的匹配，允许题目内容中包含换行
        r'^(\d+)[\.．、]\s*([\s\S]+?)(?=\s*[A-E][、.．:：]|\s*$)',
        # 更宽松的匹配，不要求题号
        r'^([\s\S]+?)(?=\s*[A][、.．:：]|\s*$)',
    ]
    
    question_number = None
    question_content = None
    
    # 尝试匹配题目编号和内容
    for pattern in question_patterns:
        match = re.search(pattern, text, re.DOTALL)
        if match:
            if len(match.groups()) > 1:
                question_number = match.group(1)
                question_content = match.group(2).strip()
            else:
                question_content = match.group(1).strip()
            logger.debug(f"匹配到题目: 题号={question_number}, 内容={question_content[:50]}...")
            break
    
    # 如果没有匹配到题目格式，尝试直接提取题目内容
    if not question_content:
        # 尝试查找第一个选项的位置
        option_patterns = [
            r'[A][、.．:：]',  # A. 或 A、 或 A: 格式
            r'选项\s*[A][：:]',  # 选项A: 格式
            r'[A]\s*[）\)]',  # A) 格式
            r'[（\(]\s*[A]\s*[）\)]'  # (A) 格式
        ]
        
        for pattern in option_patterns:
            option_match = re.search(pattern, text)
            if option_match:
                start_pos = option_match.start()
                question_content = text[:start_pos].strip()
                logger.debug(f"通过选项A位置提取题目内容: {question_content[:50]}...")
                break
        
        if not question_content:
            # 如果没有找到选项，整个文本可能就是题目
            question_content = text.strip()
            logger.debug(f"未找到选项，使用整个文本作为题目内容: {question_content[:50]}...")
    
    # 提取选项
    options = extract_options_from_text(text)
    logger.debug(f"提取到选项: {list(options.keys())}")
    
    # 如果没有提取到选项，尝试更宽松的匹配
    if not options:
        # 尝试匹配所有可能的选项格式
        all_option_patterns = [
            r'([A-E])[、.．:：]\s*([^A-E\n]+)',  # A. 文本
            r'选项\s*([A-E])[：:]\s*([^A-E\n]+)',  # 选项A: 文本
            r'([A-E])\s*[）\)]\s*([^A-E\n]+)',  # A) 文本
            r'[（\(]\s*([A-E])\s*[）\)]\s*([^A-E\n]+)'  # (A) 文本
        ]
        
        for pattern in all_option_patterns:
            all_matches = re.findall(pattern, text, re.DOTALL)
            if all_matches:
                for letter, content in all_matches:
                    options[letter.upper()] = content.strip()
                logger.debug(f"使用宽松匹配提取到选项: {list(options.keys())}")
                break
    
    # 检测答案
    detected_answer = detect_answer(text)
    logger.debug(f"检测到答案: {detected_answer}")
    
    # 如果没有足够的选项或题目内容，可能不是选择题
    if len(options) < 2 or not question_content:
        if detected_answer:
            # 如果检测到答案但没有足够的选项，可能是选项格式不规范
            logger.debug("检测到答案但选项不足，尝试从文本中提取选项")
            
            # 尝试查找所有可能的选项标记
            option_markers = re.findall(r'([A-E])[、.．:：)\s]', text)
            if len(set(option_markers)) >= 2:
                # 如果找到至少两个不同的选项标记，认为是选择题
                question_type = '选择题'
                logger.debug(f"根据选项标记判断为选择题，标记: {set(option_markers)}")
            else:
                # 否则可能是其他类型的题目
                question_type = '未分类'
                logger.debug("无法确定题目类型，标记为未分类")
        else:
            # 如果没有检测到答案也没有足够的选项，可能不是选择题
            question_type = '未分类'
            logger.debug("未检测到答案且选项不足，标记为未分类")
    else:
        # 有足够的选项，认为是选择题
        question_type = '选择题'
        logger.debug(f"有足够的选项({len(options)}个)，判断为选择题")
    
    # 构建解析结果
    result = {
        'content': question_content,
        'options': options,
        'detected_answer': detected_answer,
        'question_type': question_type,
        'question_number': question_number
    }
    
    # 如果检测到答案，设置答案
    if detected_answer:
        result['answer'] = f'选项{detected_answer}'
    
    logger.debug(f"解析完成: 题型={question_type}, 答案={detected_answer}")
    return result

class BaseDocumentParser:
    """文档解析器的基类"""
    def __init__(self, document, task=None):
        self.document = document
        self.task = task
        self.questions = []
        
    def parse(self):
        """解析文档，返回解析出的题目列表"""
        raise NotImplementedError("子类必须实现parse方法")
    
    def save_questions(self):
        """保存解析的题目到数据库"""
        # 删除该文档之前解析的题目
        deleted_count = ParsedQuestion.objects.filter(document=self.document).delete()[0]
        logger.info(f"删除了{deleted_count}个旧题目")
        
        # 保存新解析的题目
        saved_questions = []
        logger.info(f"准备保存{len(self.questions)}个新题目")
        
        for i, q in enumerate(self.questions):
            # 检测答案
            content = q.get('content', '').strip()
            detected_answer = q.get('detected_answer')
            
            # 如果任务设置了自动检测答案，则进行检测
            if self.task and self.task.auto_detect_answers:
                if not detected_answer:
                    detected_answer = detect_answer(content)
                    logger.debug(f"题目{i+1}检测到答案: {detected_answer}")
                
                # 如果检测到答案且原题目没有答案，则设置答案
                if detected_answer and not q.get('answer'):
                    q['answer'] = f'选项{detected_answer}'
                    logger.debug(f"题目{i+1}设置答案: {q['answer']}")
            
            try:
                question = ParsedQuestion.objects.create(
                    document=self.document,
                    content=content,
                    answer=q.get('answer', '').strip() if q.get('answer') else None,
                    detected_answer=detected_answer,
                    page_number=q.get('page_number', 1),
                    question_type=q.get('question_type', '未分类')
                )
                saved_questions.append(question)
                logger.debug(f"成功保存题目{i+1}")
            except Exception as e:
                logger.error(f"保存题目{i+1}失败: {str(e)}")
                logger.error(f"题目内容: {content[:100]}...")
        
        logger.info(f"成功保存{len(saved_questions)}/{len(self.questions)}个题目")
            
        # 如果有任务对象，更新任务状态
        if self.task:
            self.task.questions_count = len(saved_questions)
            self.task.status = 'completed'
            self.task.completed_at = timezone.now()
            self.task.save()
            logger.info(f"更新任务状态: completed, 题目数量: {len(saved_questions)}")
            
        return saved_questions
    
    def handle_error(self, error_message):
        """处理解析过程中的错误"""
        if self.task:
            self.task.status = 'failed'
            self.task.error_message = error_message
            self.task.completed_at = timezone.now()
            self.task.save()
        logger.error(f"文档解析错误: {error_message}")

class PDFParser(BaseDocumentParser):
    """PDF文档解析器"""
    def parse(self):
        try:
            # 确保文件存在
            file_path = self.document.file.path
            if not os.path.exists(file_path):
                self.handle_error("文件不存在")
                return []
            
            # 更新任务状态
            if self.task:
                self.task.status = 'processing'
                self.task.save()
                
            # 打开PDF文件
            pdf_document = fitz.open(file_path)
            
            # 题目识别的正则表达式
            question_patterns = [
                r'^\d+\.\s+.+',  # 数字开头：1. 题目内容
                r'^[一二三四五六七八九十]+[、.．]\s*.+',  # 中文数字开头：一、题目内容
                r'^第[一二三四五六七八九十\d]+题\s*.+',  # "第X题"开头
                r'^[（\(]\s*\d+\s*[）\)]\s*.+',  # 带括号的数字：(1) 题目内容
                r'^题\s*\d+[\.．、]?\s*.+',  # 题号+数字格式：题1. 题目内容
                r'^问题\s*\d+[：:]\s*.+'  # 问题+数字格式：问题1：题目内容
            ]
            
            # 题型识别的正则表达式
            question_type_patterns = [
                r'^[一二三四五六七八九十]+[、.．]\s*(单项选择题|多项选择题|判断题|填空题|简答题|计算题|分析题)',  # 一、单项选择题
                r'^(单项选择题|多项选择题|判断题|填空题|简答题|计算题|分析题)',  # 直接以题型开头
                r'^[（\(]\s*(单项选择题|多项选择题|判断题|填空题|简答题|计算题|分析题)\s*[）\)]'  # (单项选择题)
            ]
            
            # 答案部分识别的正则表达式
            answer_section_patterns = [
                r'^答案[：:]',  # 答案：
                r'^解答[：:]',  # 解答：
                r'^参考答案[：:]',  # 参考答案：
                r'^答案与解析[：:]',  # 答案与解析：
                r'^答案及解析[：:]'  # 答案及解析：
            ]
            
            current_question = ""
            current_answer = ""
            in_answer = False
            current_page = 1
            current_question_type = "未分类"
            
            # 首先尝试提取整个文档的文本，检查是否有明确的题目和答案部分
            full_text = ""
            for page_num in range(len(pdf_document)):
                page = pdf_document[page_num]
                full_text += page.get_text() + "\n"
            
            # 尝试查找答案部分的起始位置
            answer_section_start = -1
            for pattern in answer_section_patterns:
                match = re.search(pattern, full_text, re.MULTILINE)
                if match:
                    answer_section_start = match.start()
                    break
            
            # 如果找到了答案部分，将文档分为题目部分和答案部分
            questions_text = full_text
            answers_text = ""
            if answer_section_start != -1:
                questions_text = full_text[:answer_section_start].strip()
                answers_text = full_text[answer_section_start:].strip()
                
                # 尝试使用parse_multiple_questions解析题目部分
                parsed_questions = parse_multiple_questions(questions_text)
                if parsed_questions:
                    # 如果成功解析出题目，尝试从答案部分匹配答案
                    for q in parsed_questions:
                        question_number = q.get('question_number')
                        if question_number:
                            # 尝试在答案部分查找对应题号的答案
                            answer_pattern = r'(?:^|\n)(?:' + re.escape(str(question_number)) + r'|第\s*' + re.escape(str(question_number)) + r'\s*题)[\.．、：:]\s*([^\n]+)'
                            answer_match = re.search(answer_pattern, answers_text)
                            if answer_match:
                                q['answer'] = answer_match.group(1).strip()
                        
                        # 添加页码信息
                        q['page_number'] = 1  # 默认为第一页
                        
                        # 添加到结果列表
                        self.questions.append(q)
                    
                    # 如果成功解析出题目，直接返回结果
                    if self.questions:
                        return self.questions
            
            # 如果上述方法未能成功解析，使用逐页解析的方法
            for page_num in range(len(pdf_document)):
                page = pdf_document[page_num]
                text = page.get_text()
                lines = text.split('\n')
                
                for line in lines:
                    line = line.strip()
                    if not line:
                        continue
                    
                    # 检查是否是题型标题
                    is_question_type = any(re.match(pattern, line) for pattern in question_type_patterns)
                    if is_question_type:
                        for pattern in question_type_patterns:
                            match = re.match(pattern, line)
                            if match:
                                current_question_type = match.group(1)
                                break
                        continue
                    
                    # 检查是否是答案部分
                    is_answer_section = any(re.match(pattern, line) for pattern in answer_section_patterns)
                    if is_answer_section:
                        in_answer = True
                        continue
                    
                    # 检查是否是新题目
                    is_new_question = any(re.match(pattern, line) for pattern in question_patterns)
                    
                    # 如果遇到新题目且当前已有题目，保存先前的题目
                    if is_new_question and current_question:
                        # 尝试解析选择题
                        if "选择题" in current_question_type:
                            parsed = parse_multiple_choice_question(current_question)
                            if parsed:
                                self.questions.append({
                                    'content': parsed['content'],
                                    'answer': current_answer.strip() if current_answer else None,
                                    'detected_answer': parsed['detected_answer'],
                                    'page_number': current_page,
                                    'question_type': parsed['question_type'] or current_question_type
                                })
                            else:
                                # 如果解析失败，使用原始方法
                                self.questions.append({
                                    'content': current_question.strip(),
                                    'answer': current_answer.strip() if current_answer else None,
                                    'page_number': current_page,
                                    'question_type': current_question_type
                                })
                        else:
                            # 非选择题使用原始方法
                            self.questions.append({
                                'content': current_question.strip(),
                                'answer': current_answer.strip() if current_answer else None,
                                'page_number': current_page,
                                'question_type': current_question_type
                            })
                        
                        # 重置当前题目和答案
                        current_question = line
                        current_answer = ""
                        in_answer = False
                        current_page = page_num + 1
                    elif is_new_question:
                        # 第一个题目
                        current_question = line
                        current_page = page_num + 1
                    elif in_answer:
                        # 继续添加到答案
                        current_answer += line + " "
                    elif any(line.startswith(prefix) for prefix in ["答案:", "解答:", "答:", "解:"]):
                        # 进入答案部分
                        in_answer = True
                        prefix_length = line.find(":") + 1
                        current_answer += line[prefix_length:].strip() + " "
                    else:
                        # 继续添加到题目
                        current_question += " " + line
            
            # 处理最后一个题目
            if current_question:
                # 尝试解析选择题
                if "选择题" in current_question_type:
                    parsed = parse_multiple_choice_question(current_question)
                    if parsed:
                        self.questions.append({
                            'content': parsed['content'],
                            'answer': current_answer.strip() if current_answer else None,
                            'detected_answer': parsed['detected_answer'],
                            'page_number': current_page,
                            'question_type': parsed['question_type'] or current_question_type
                        })
                    else:
                        # 如果解析失败，使用原始方法
                        self.questions.append({
                            'content': current_question.strip(),
                            'answer': current_answer.strip() if current_answer else None,
                            'page_number': current_page,
                            'question_type': current_question_type
                        })
                
            # 如果没有成功解析出题目，尝试使用parse_multiple_questions解析整个文档
            if not self.questions:
                parsed_questions = parse_multiple_questions(full_text)
                for q in parsed_questions:
                    # 添加页码信息
                    q['page_number'] = 1  # 默认为第一页
                    self.questions.append(q)
            
            return self.questions
            
        except Exception as e:
            error_message = f"PDF解析错误: {str(e)}"
            self.handle_error(error_message)
            return []
    
    def _determine_question_type(self, question_text):
        """确定题目类型"""
        question_text = question_text.lower()
        if "单项选择题" in question_text or "单选题" in question_text:
            return "单选题"
        elif "多项选择题" in question_text or "多选题" in question_text:
            return "多选题"
        elif "选择" in question_text:
            return "选择题"
        elif "判断" in question_text:
            return "判断题"
        elif "填空" in question_text:
            return "填空题"
        elif "简答" in question_text or "问答" in question_text:
            return "简答题"
        elif "计算" in question_text:
            return "计算题"
        elif "解析" in question_text or "分析" in question_text:
            return "分析题"
        return "未分类"

class DocxParser(BaseDocumentParser):
    """DOCX文档解析器"""
    def parse(self):
        try:
            # 确保文件存在
            file_path = self.document.file.path
            if not os.path.exists(file_path):
                self.handle_error("文件不存在")
                return []
            
            # 更新任务状态
            if self.task:
                self.task.status = 'processing'
                self.task.save()
            
            # 打开DOCX文件
            doc = docx.Document(file_path)
            
            # 题目识别的正则表达式
            question_patterns = [
                r'^\d+\.\s+.+',  # 数字开头：1. 题目内容
                r'^[一二三四五六七八九十]+[、.．]\s*.+',  # 中文数字开头：一、题目内容
                r'^第[一二三四五六七八九十\d]+题\s*.+',  # "第X题"开头
                r'^[（\(]\s*\d+\s*[）\)]\s*.+',  # 带括号的数字：(1) 题目内容
                r'^题\s*\d+[\.．、]?\s*.+',  # 题号+数字格式：题1. 题目内容
                r'^问题\s*\d+[：:]\s*.+'  # 问题+数字格式：问题1：题目内容
            ]
            
            # 题型识别的正则表达式
            question_type_patterns = [
                r'^[一二三四五六七八九十]+[、.．]\s*(单项选择题|多项选择题|判断题|填空题|简答题|计算题|分析题)',  # 一、单项选择题
                r'^(单项选择题|多项选择题|判断题|填空题|简答题|计算题|分析题)',  # 直接以题型开头
                r'^[（\(]\s*(单项选择题|多项选择题|判断题|填空题|简答题|计算题|分析题)\s*[）\)]'  # (单项选择题)
            ]
            
            # 答案部分识别的正则表达式
            answer_section_patterns = [
                r'^答案[：:]',  # 答案：
                r'^解答[：:]',  # 解答：
                r'^参考答案[：:]',  # 参考答案：
                r'^答案与解析[：:]',  # 答案与解析：
                r'^答案及解析[：:]'  # 答案及解析：
            ]
            
            current_question = ""
            current_answer = ""
            in_answer = False
            current_page = 1  # DOCX没有页码概念，默认为1
            current_question_type = "未分类"
            
            # 首先提取整个文档的文本
            full_text = "\n".join([para.text for para in doc.paragraphs])
            
            # 尝试查找答案部分的起始位置
            answer_section_start = -1
            for pattern in answer_section_patterns:
                match = re.search(pattern, full_text, re.MULTILINE)
                if match:
                    answer_section_start = match.start()
                    break
            
            # 如果找到了答案部分，将文档分为题目部分和答案部分
            questions_text = full_text
            answers_text = ""
            if answer_section_start != -1:
                questions_text = full_text[:answer_section_start].strip()
                answers_text = full_text[answer_section_start:].strip()
                
                # 尝试使用parse_multiple_questions解析题目部分
                parsed_questions = parse_multiple_questions(questions_text)
                if parsed_questions:
                    # 如果成功解析出题目，尝试从答案部分匹配答案
                    for q in parsed_questions:
                        question_number = q.get('question_number')
                        if question_number:
                            # 尝试在答案部分查找对应题号的答案
                            answer_pattern = r'(?:^|\n)(?:' + re.escape(str(question_number)) + r'|第\s*' + re.escape(str(question_number)) + r'\s*题)[\.．、：:]\s*([^\n]+)'
                            answer_match = re.search(answer_pattern, answers_text)
                            if answer_match:
                                q['answer'] = answer_match.group(1).strip()
                        
                        # 添加页码信息
                        q['page_number'] = 1  # 默认为第一页
                        
                        # 添加到结果列表
                        self.questions.append(q)
                    
                    # 如果成功解析出题目，直接返回结果
                    if self.questions:
                        return self.questions
            
            # 如果上述方法未能成功解析，使用逐段解析的方法
            for para in doc.paragraphs:
                line = para.text.strip()
                if not line:
                    continue
                
                # 检查是否是题型标题
                is_question_type = any(re.match(pattern, line) for pattern in question_type_patterns)
                if is_question_type:
                    for pattern in question_type_patterns:
                        match = re.match(pattern, line)
                        if match:
                            current_question_type = match.group(1)
                            break
                    continue
                
                # 检查是否是答案部分
                is_answer_section = any(re.match(pattern, line) for pattern in answer_section_patterns)
                if is_answer_section:
                    in_answer = True
                    continue
                
                # 检查是否是新题目
                is_new_question = any(re.match(pattern, line) for pattern in question_patterns)
                
                # 如果遇到新题目且当前已有题目，保存先前的题目
                if is_new_question and current_question:
                    # 尝试解析选择题
                    if "选择题" in current_question_type:
                        parsed = parse_multiple_choice_question(current_question)
                        if parsed:
                            self.questions.append({
                                'content': parsed['content'],
                                'answer': current_answer.strip() if current_answer else None,
                                'detected_answer': parsed['detected_answer'],
                                'page_number': current_page,
                                'question_type': parsed['question_type'] or current_question_type
                            })
                        else:
                            # 如果解析失败，使用原始方法
                            self.questions.append({
                                'content': current_question.strip(),
                                'answer': current_answer.strip() if current_answer else None,
                                'page_number': current_page,
                                'question_type': current_question_type
                            })
                    else:
                        # 非选择题使用原始方法
                        self.questions.append({
                            'content': current_question.strip(),
                            'answer': current_answer.strip() if current_answer else None,
                            'page_number': current_page,
                            'question_type': current_question_type
                        })
                    
                    # 重置当前题目和答案
                    current_question = line
                    current_answer = ""
                    in_answer = False
                elif is_new_question:
                    # 第一个题目
                    current_question = line
                elif in_answer:
                    # 继续添加到答案
                    current_answer += line + " "
                elif any(line.startswith(prefix) for prefix in ["答案:", "解答:", "答:", "解:"]):
                    # 进入答案部分
                    in_answer = True
                    prefix_length = line.find(":") + 1
                    current_answer += line[prefix_length:].strip() + " "
                else:
                    # 继续添加到题目
                    current_question += " " + line
            
            # 处理最后一个题目
            if current_question:
                # 尝试解析选择题
                if "选择题" in current_question_type:
                    parsed = parse_multiple_choice_question(current_question)
                    if parsed:
                        self.questions.append({
                            'content': parsed['content'],
                            'answer': current_answer.strip() if current_answer else None,
                            'detected_answer': parsed['detected_answer'],
                            'page_number': current_page,
                            'question_type': parsed['question_type'] or current_question_type
                        })
                    else:
                        # 如果解析失败，使用原始方法
                        self.questions.append({
                            'content': current_question.strip(),
                            'answer': current_answer.strip() if current_answer else None,
                            'page_number': current_page,
                            'question_type': current_question_type
                        })
                
            # 如果没有成功解析出题目，尝试使用parse_multiple_questions解析整个文档
            if not self.questions:
                parsed_questions = parse_multiple_questions(full_text)
                for q in parsed_questions:
                    # 添加页码信息
                    q['page_number'] = 1  # 默认为第一页
                    self.questions.append(q)
            
            return self.questions
            
        except Exception as e:
            error_message = f"DOCX解析错误: {str(e)}"
            self.handle_error(error_message)
            return []
    
    def _determine_question_type(self, question_text):
        """确定题目类型"""
        question_text = question_text.lower()
        if "单项选择题" in question_text or "单选题" in question_text:
            return "单选题"
        elif "多项选择题" in question_text or "多选题" in question_text:
            return "多选题"
        elif "选择" in question_text:
            return "选择题"
        elif "判断" in question_text:
            return "判断题"
        elif "填空" in question_text:
            return "填空题"
        elif "简答" in question_text or "问答" in question_text:
            return "简答题"
        elif "计算" in question_text:
            return "计算题"
        elif "解析" in question_text or "分析" in question_text:
            return "分析题"
        return "未分类"

class TextParser(BaseDocumentParser):
    """文本文件解析器"""
    def parse(self):
        try:
            # 确保文件存在
            file_path = self.document.file.path
            if not os.path.exists(file_path):
                self.handle_error("文件不存在")
                return []
            
            # 更新任务状态
            if self.task:
                self.task.status = 'processing'
                self.task.save()
            
            # 读取文本文件
            with open(file_path, 'r', encoding='utf-8') as file:
                text = file.read()
            
            # 尝试使用parse_multiple_questions解析整个文本
            parsed_questions = parse_multiple_questions(text)
            
            # 如果成功解析出题目，添加到结果列表
            for q in parsed_questions:
                # 添加页码信息
                q['page_number'] = 1  # 默认为第一页
                self.questions.append(q)
            
            return self.questions
            
        except Exception as e:
            error_message = f"文本文件解析错误: {str(e)}"
            self.handle_error(error_message)
            return []

class ExcelParser(BaseDocumentParser):
    """Excel文档解析器"""
    def parse(self):
        try:
            # 确保文件存在
            file_path = self.document.file.path
            if not os.path.exists(file_path):
                self.handle_error("文件不存在")
                return []
            
            # 更新任务状态
            if self.task:
                self.task.status = 'processing'
                self.task.save()
            
            logger.info(f"开始解析Excel文档: {file_path}")
            
            try:
                # 尝试导入pandas
                import pandas as pd
                
                # 读取Excel文件
                df = pd.read_excel(file_path)
                
                # 获取列名
                columns = df.columns.tolist()
                logger.info(f"Excel列名: {columns}")
                
                # 查找可能包含题目的列
                question_columns = []
                for col in columns:
                    col_lower = str(col).lower()
                    if '题目' in col_lower or '问题' in col_lower or '题干' in col_lower or 'question' in col_lower:
                        question_columns.append(col)
                
                # 查找可能包含答案的列
                answer_columns = []
                for col in columns:
                    col_lower = str(col).lower()
                    if '答案' in col_lower or '解析' in col_lower or 'answer' in col_lower:
                        answer_columns.append(col)
                
                logger.info(f"可能的题目列: {question_columns}")
                logger.info(f"可能的答案列: {answer_columns}")
                
                # 如果没有找到题目列，尝试使用所有列
                if not question_columns:
                    logger.warning("未找到明确的题目列，尝试使用所有列")
                    question_columns = columns
                
                # 解析每一行
                for index, row in df.iterrows():
                    for q_col in question_columns:
                        question_content = str(row[q_col])
                        if not question_content or question_content.lower() == 'nan':
                            continue
                        
                        # 查找对应的答案
                        answer = None
                        for a_col in answer_columns:
                            if not pd.isna(row[a_col]):
                                answer = str(row[a_col])
                                break
                        
                        # 检测答案
                        detected_answer = detect_answer(question_content)
                        
                        # 添加到题目列表
                        self.questions.append({
                            'content': question_content,
                            'answer': answer,
                            'detected_answer': detected_answer,
                            'page_number': 1,  # Excel没有页码概念
                            'question_type': '选择题' if detected_answer else '未分类'
                        })
                
                logger.info(f"从Excel解析出{len(self.questions)}个题目")
                
            except ImportError:
                logger.error("缺少pandas库，无法解析Excel文件")
                self.handle_error("缺少pandas库，无法解析Excel文件")
                return []
            
            return self.questions
            
        except Exception as e:
            error_message = f"解析Excel文档错误: {str(e)}"
            logger.error(error_message)
            self.handle_error(error_message)
            return []

def get_parser_for_document(document, task=None):
    """根据文档类型获取适合的解析器"""
    if not document:
        raise ValueError("文档不能为空")
    
    if not document.file:
        raise ValueError("文档没有关联文件")
    
    file_path = document.file.path
    if not os.path.exists(file_path):
        raise ValueError(f"文件不存在: {file_path}")
    
    file_ext = os.path.splitext(file_path)[1].lower()
    logger.info(f"文档类型: {file_ext}, 文件路径: {file_path}")
    
    # 根据文件扩展名选择解析器
    if file_ext == '.pdf':
        logger.info(f"使用PDF解析器解析文档: {document.title}")
        return PDFParser(document, task)
    elif file_ext in ['.docx', '.doc']:
        logger.info(f"使用Word解析器解析文档: {document.title}")
        return DocxParser(document, task)
    elif file_ext in ['.txt']:
        logger.info(f"使用文本解析器解析文档: {document.title}")
        return TextParser(document, task)
    elif file_ext in ['.xlsx', '.xls']:
        logger.info(f"使用Excel解析器解析文档: {document.title}")
        return ExcelParser(document, task)
    else:
        raise ValueError(f"不支持的文件类型: {file_ext}") 